/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.context.properties.bind;

import org.springframework.boot.context.properties.source.ConfigurationPropertyName;

/**
 * 可用于在元素 {@link Binder} 绑定过程中处理额外逻辑的回调接口。
 *
 * @author Phillip Webb
 * @author Madhura Bhave
 * @since 2.0.0
 */
public interface BindHandler {

	/**
	 * 默认的空操作绑定处理器。
	 */
	BindHandler DEFAULT = new BindHandler() {

	};

	/**
	 * 当元素绑定开始但尚未确定任何结果时调用。
	 *
	 * @param <T> 可绑定的源类型
	 * @param name 正在绑定的元素名称
	 * @param target 正在绑定的对象
	 * @param context 绑定上下文
	 * @return 实际用于绑定的对象（可能为 {@code null}）
	 */
	default <T> Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target, BindContext context) {
		return target;
	}

	/**
	 * 当元素绑定成功结束时调用。实现类可以修改最终返回的结果或执行额外的校验。
	 *
	 * @param name 正在绑定的元素名称
	 * @param target 正在绑定的对象
	 * @param context 绑定上下文
	 * @param result 绑定结果（永不为 {@code null}）
	 * @return 应实际使用的结果（可能为 {@code null}）
	 */
	default Object onSuccess(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) {
		return result;
	}

	/**
	 * 当元素绑定结束且结果未绑定时调用，并且即将返回一个新创建的实例。
	 * 实现类可以修改最终返回的结果或执行额外的校验。
	 *
	 * @param name 正在绑定的元素名称
	 * @param target 正在绑定的对象
	 * @param context 绑定上下文
	 * @param result 新创建的实例（永不为 {@code null}）
	 * @return 应实际使用的结果（不得为 {@code null}）
	 * @since 2.2.2
	 */
	default Object onCreate(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result) {
		return result;
	}

	/**
	 * 当绑定因任何原因失败时调用（包括 {@link #onSuccess} 或 {@link #onCreate} 调用导致的失败）。
	 * 实现类可以选择吞掉异常并返回替代结果。
	 *
	 * @param name 正在绑定的元素名称
	 * @param target 正在绑定的对象
	 * @param context 绑定上下文
	 * @param error 错误原因（如果异常仍然有效，可以重新抛出）
	 * @return 应实际使用的结果（可能为 {@code null}）
	 * @throws Exception 如果绑定无效
	 */
	default Object onFailure(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Exception error)
			throws Exception {
		throw error;
	}

	/**
	 * 当绑定完成（无论是绑定成功还是未绑定结果）时调用。
	 * 如果绑定失败，则不会调用此方法，即使处理器从 {@link #onFailure} 返回了结果。
	 *
	 * @param name 正在绑定的元素名称
	 * @param target 正在绑定的对象
	 * @param context 绑定上下文
	 * @param result 绑定结果（可能为 {@code null}）
	 * @throws Exception 如果绑定无效
	 */
	default void onFinish(ConfigurationPropertyName name, Bindable<?> target, BindContext context, Object result)
			throws Exception {
	}

}
